﻿using System;
using System.Web.Mvc;
using SlamCms.Configuration;
using SlamCms.Data;

namespace SlamCms.Web.Mvc
{
	public enum HttpsBehavior
	{
		Disabled,
		Enabled
	}

	[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true, AllowMultiple = false)]
	public class HttpsAttribute : FilterAttribute, IAuthorizationFilter
	{
		public HttpsAttribute(HttpsBehavior httpsBehavior)
		{
			HttpsBehavior = httpsBehavior;
		}

		public int Port { get; set; }
		public string HostName { get; set; }
		public HttpsBehavior HttpsBehavior { get; set; }

		public virtual void OnAuthorization(AuthorizationContext filterContext)
		{
			if (filterContext == null)
				throw new ArgumentNullException("filterContext");

			if (filterContext.IsChildAction || ConfigurationHelpers.GetEnvironmentSetting(Constants.Settings.HttpsEnabled, true))
				return;

			if (HttpsBehavior == HttpsBehavior.Enabled && !filterContext.HttpContext.Request.IsSecureConnection)
				HandleNonHttpsRequest(filterContext);
			else if (HttpsBehavior == HttpsBehavior.Disabled && filterContext.HttpContext.Request.IsSecureConnection)
				HandleHttpsRequest(filterContext);
		}

		protected virtual void HandleNonHttpsRequest(AuthorizationContext filterContext)
		{
			if (!string.Equals(filterContext.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase))
			{
				return;
			}

			var url = RebuildURL(filterContext, "https");

			filterContext.Result = new RedirectResult(url);
		}

		protected virtual void HandleHttpsRequest(AuthorizationContext filterContext)
		{
			if (!string.Equals(filterContext.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase))
			{
				return;
			}

			var url = RebuildURL(filterContext, "http");

			filterContext.Result = new RedirectResult(url);
		}

		protected virtual string RebuildURL(AuthorizationContext filterContext, string scheme)
		{
			var host = string.IsNullOrEmpty(HostName) ? filterContext.HttpContext.Request.Url.Host : HostName;
			var port = Port <= 0 ? string.Empty : ":" + Port;
			return string.Format("{0}://{1}{2}{3}", scheme, host, port, filterContext.HttpContext.Request.RawUrl);
		}
	}
}